package cn.yunlang.zhangZhongFei.job;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import cn.yunlang.zhangZhongFei.constant.CacheConstant;
import cn.yunlang.zhangZhongFei.entity.Award;
import cn.yunlang.zhangZhongFei.entity.WinAward;
import cn.yunlang.zhangZhongFei.service.AwardService;
import cn.yunlang.zhangZhongFei.service.WinAwardService;
import cn.yunlang.zhangZhongFei.util.RedisUtil;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Set;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

@Slf4j
@Configuration
@EnableScheduling
public class AwardJob {

  @Resource private AwardService awardService;
  @Resource private WinAwardService winAwardService;
  @Resource private RedisUtil redisUtil;

  @Scheduled(cron = "0 */1 * * * ?") // 每分钟执行一次
  public void award() {
    log.info("========== 开始执行抽奖定时任务 ==========");
    Date now = new Date();
    log.info("当前时间: {}", now);

    // 处理已结束但未抽奖的活动
    List<Award> endAwardList =
        awardService.list(
            new LambdaQueryWrapper<Award>().eq(Award::getState, "1").le(Award::getEndTime, now));

    if (endAwardList.isEmpty()) {
      log.info("当前没有需要处理的已结束活动");
    } else {
      log.info("找到{}个已结束的活动需要处理: {}", endAwardList.size());
    }

    for (Award award : endAwardList) {
      try {
        log.info("========== 开始处理活动{}的抽奖，活动名称：{} ==========", award.getId(), award.getAwardName());
        log.info("活动结束时间: {}", award.getEndTime());

        // 更新活动状态为已结束
        award.setState("2");
        boolean updateSuccess = awardService.updateById(award);
        if (!updateSuccess) {
          log.error("更新活动{}状态失败", award.getId());
          continue;
        }
        log.info("更新活动{}状态为已结束成功", award.getId());

        String keyBegin = CacheConstant.AWARD + award.getId();
        String joinUsersKey = keyBegin + ":joinUsers";
        log.info("开始获取活动{}的参与用户，Redis key: {}", award.getId(), joinUsersKey);

        // 获取参与用户列表
        Set<String> joinUsers = redisUtil.sMembers(joinUsersKey);
        if (joinUsers == null || joinUsers.isEmpty()) {
          log.warn("活动{}没有参与用户，Redis key: {}", award.getId(), joinUsersKey);
          continue;
        }
        log.info("活动{}共有{}个参与用户: {}", award.getId(), joinUsers.size(), joinUsers);

        // 获取奖品数量 - 优先使用数据库中的数量
        int awardCount = award.getAwardCount();
        log.info("活动{}的数据库奖品数量: {}", award.getId(), awardCount);

        if (awardCount <= 0) {
          log.warn("活动{}奖品数量为0或负数", award.getId());
          continue;
        }

        int joinCount = joinUsers.size();
        log.info("活动{}开始抽奖，奖品数量: {}, 参与人数: {}", award.getId(), awardCount, joinCount);

        // 随机抽取中奖用户
        List<String> userIds = new ArrayList<>(joinUsers);
        Collections.shuffle(userIds);

        // 确定中奖人数
        int winCount = Math.min(awardCount, joinCount);
        log.info("活动{}将抽取{}名中奖用户", award.getId(), winCount);

        // 记录中奖信息
        List<WinAward> winAwards = new ArrayList<>();
        for (int i = 0; i < winCount; i++) {
          String userId = userIds.get(i);
          WinAward winAward = new WinAward();
          BeanUtils.copyProperties(award, winAward, "id", "createTime");
          winAward.setUserId(Long.valueOf(userId));
          winAward.setAwardId(award.getId());
          winAwards.add(winAward);
          log.info("用户{}被选中为中奖用户", userId);
        }

        // 批量保存中奖记录
        if (!winAwards.isEmpty()) {
          log.info("开始保存活动{}的中奖记录，共{}条", award.getId(), winAwards.size());
          try {
            boolean saveSuccess = winAwardService.saveBatch(winAwards);
            if (!saveSuccess) {
              log.error("保存活动{}的中奖记录失败", award.getId());
              continue;
            }
            log.info("保存活动{}的中奖记录成功", award.getId());
          } catch (Exception e) {
            log.error("保存活动{}的中奖记录时发生异常", award.getId(), e);
            continue;
          }
        } else {
          log.warn("活动{}没有中奖记录需要保存", award.getId());
        }

        // 清理缓存
        log.info("开始清理活动{}的缓存", award.getId());
        redisUtil.delAll(keyBegin);
        log.info("清理活动{}的缓存完成", award.getId());

        log.info("========== 活动{}抽奖处理完成 ==========", award.getId());
      } catch (Exception e) {
        log.error("处理活动{}抽奖时发生错误", award.getId(), e);
      }
    }

    // 开始新的活动（只处理未开始的活动）
    List<Award> startAwardList =
        awardService.list(
            new LambdaQueryWrapper<Award>()
                .eq(Award::getState, "0")
                .le(Award::getStartTime, now)
                .gt(Award::getEndTime, now));

    if (!startAwardList.isEmpty()) {
      log.info("找到{}个需要开始的活动", startAwardList.size());
      for (Award award : startAwardList) {
        try {
          award.setState("1");
          boolean updateSuccess = awardService.updateById(award);
          log.info("更新活动{}状态为进行中: {}", award.getId(), updateSuccess);
        } catch (Exception e) {
          log.error("更新活动{}状态为进行中时发生错误", award.getId(), e);
        }
      }
    }

    log.info("========== 抽奖定时任务执行完成 ==========");
  }
}
